package cn.com.dragonpass.psystem.common.configuration;

import cn.com.dragonpass.common.utils.StringUtils;
import cn.com.dragonpass.logback.interceptor.LogInterceptor;
import cn.com.dragonpass.pmodel.common.DataEntity;
import cn.com.dragonpass.psystem.common.interceptor.LoginInterceptor;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.ClientAbortException;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Locale;

@Slf4j
@Aspect
@Configuration
public class GlobalWebMvcConfigurer extends WebMvcConfigurerAdapter {


    @Autowired
    private SessionContext userContext;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeResolverInterceptor());
        registry.addInterceptor(new LogInterceptor());
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }

//    @Bean
//    public FilterRegistrationBean repeatedlyReadFilter() {
//        FilterRegistrationBean registration = new FilterRegistrationBean();
//        registration.setFilter(new RepeatedlyReadFilter() {
//            @Override
//            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//                try {
//                    super.doFilter(request, response, chain);
//                } catch (ClientAbortException e) {
//                    log.error(e.getMessage());
//                }
//            }
//        });
//        registration.addUrlPatterns("/*");
//        return registration;
//    }

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        exceptionResolvers.add(0, new ExceptionHandlerExceptionResolver() {

            @Override
            protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
                // 重写去掉 ClientAbortException 异常堆栈打印
                if (exception instanceof ClientAbortException) {
                    logger.warn(exception.getClass().getName() + ":  " + exception.getMessage());
                    return new ModelAndView(new MappingJackson2JsonView())
                            .addAllObjects(JSON.parseObject(JSON.toJSONString(new DataEntity<String>("0", "network error", null))));
                }
                return null;
            }
        });
    }

    public LocaleChangeInterceptor localeResolverInterceptor() {

        return new LocaleChangeInterceptor() {

            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {

                String lg = null;
                String region = null;

                lg = request.getHeader("Accept-Language");

                if (StringUtils.isBlank(lg)) {
                    lg = "zh-cn";
                }

                if (lg.contains(",")) {
                    lg = lg.split(",")[0].toLowerCase();
                }

                if (lg.contains("-")) {
                    String[] split = lg.split("-");
                    lg = split[0];
                    region = split[1];
                }

                LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
                if (localeResolver == null) {
                    throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
                }
                try {
                    Locale locale = region != null ? new Locale(lg, region) : new Locale(lg);
                    if (!response.isCommitted()) {
                        localeResolver.setLocale(request, response, locale);
                        userContext.setLocale(locale, region != null ? lg + "-" + region : lg);
                    }
                } catch (IllegalArgumentException var7) {
                    if (!this.isIgnoreInvalidLocale()) {
                        throw var7;
                    }
                    this.logger.debug("Ignoring invalid locale value [" + lg + "]: " + var7.getMessage());
                }
                return true;
            }
        };
    }

//    public static class LogInterceptor implements HandlerInterceptor {
//
//        private static final Logger logger = LoggerFactory.getLogger("");
//
//        @Override
//        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) {
//            try {
//                String traceId = request.getHeader("HTTP-HEADER-TRACE-ID");
//                if (StringUtils.isEmpty(traceId)) {
//                    traceId = TraceLogUtils.getTraceId();
//                }
//                MDC.put("LOG_TRACE_ID", "TID[" + traceId + "]");
//
//                if (!(o instanceof HandlerMethod)) {
//                    return true;
//                }
//
//                boolean logIn = true;
//                Method cmethod = ((HandlerMethod) o).getMethod();
//                Log log = cmethod.getAnnotation(Log.class);
//                if (log != null) {
//                    logIn = log.in();
//                }
//
//                if (!logIn) {
//                    return true;
//                }
//
//                String remoteIp = RequestIPUtils.getIpAddr(request);
//                String method = request.getMethod();
//                String headString = TraceLogUtils.getHeaderString(request);
//                String uri = request.getRequestURI();
//                String contentType = request.getContentType();
//                if (headString.length() > 500) {
//                    headString = headString.substring(0, 500);
//                }
//
//                String reqParam = "(blank)";
//                List<String> paramList = new ArrayList<>();
//                try {
//                    // 请求日志  非JSON格式参数
//                    Enumeration<String> parameterNames = request.getParameterNames();
//                    while (parameterNames.hasMoreElements()) {
//                        String key = parameterNames.nextElement();
//                        String value = request.getParameter(key);
//                        paramList.add(key + "=" + value);
//                    }
//                    // 上传文件信息
//                    if (contentType != null && contentType.toLowerCase().contains("multipart")) {
//                        Collection<Part> parts = request.getParts();
//                        for (Part p : parts) {
//                            paramList.add(JSON.toJSONString(p));
//                        }
//                    }
//                    if (paramList.size() > 0) {
//                        reqParam = paramList.toString();
//                    }
//                    // 请求日志 JSON格式参数
//                    if (contentType != null && contentType.toLowerCase().contains(MediaType.APPLICATION_JSON_VALUE) && request instanceof RepeatedlyReadRequestWrapper) {
//                        if (paramList.size() == 0) {
//                            reqParam = "";
//                        }
//                        RepeatedlyReadRequestWrapper requestWrapper = (RepeatedlyReadRequestWrapper) request;
//                        reqParam += TraceLogUtils.getBodyString(requestWrapper);
//                    }
//                } catch (Throwable e) {
//                    logger.error(e.getClass() + "  " + e.getMessage(), e);
//                }
//
//                logger.info("{} {} --> {} {} headers[{}] upstream IP[{}]",
//                        method, uri, reqParam,
//                        StringUtils.isBlank(contentType) ? "(contentType is blank)" : "",
//                        headString, remoteIp);
//            } catch (Throwable e) {
//                logger.error(e.getClass() + "  " + e.getMessage(), e);
//            }
//            request.setAttribute("_timestart", System.currentTimeMillis());
//            return true;
//        }
//
//        @Override
//        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) {
//        }
//
//        @Override
//        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
//            try {
//                if (!(o instanceof HandlerMethod)) {
//                    return;
//                }
//
//                long respTime = 0;
//                if (request.getAttribute("_timestart") != null) {
//                    respTime = System.currentTimeMillis() - (long) request.getAttribute("_timestart");
//                }
//                String result = (String) request.getAttribute("_resp");
//
//                logger.info("{} {} <-- RT[{}ms] {}", request.getMethod(), request.getRequestURI(), respTime, result);
//            } finally {
//                MDC.remove("LOG_TRACE_ID");
//            }
//        }
//    }

//    @AfterReturning(pointcut =
//            "@annotation(org.springframework.web.bind.annotation.RequestMapping)" +
//            "|| @annotation(org.springframework.web.bind.annotation.PostMapping)  " +
//            "|| @annotation(org.springframework.web.bind.annotation.GetMapping)  " +
//            "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping) " +
//            "|| @annotation(org.springframework.web.bind.annotation.PutMapping) ", returning = "ret")
//    public void doAfter(JoinPoint point, Object ret) {
//        if (ret == null) {
//            return;
//        }
//        Method cmethod = ((MethodSignature) point.getSignature()).getMethod();
//
//        boolean logOut = true;
//        Log log = cmethod.getAnnotation(Log.class);
//        if (log != null) {
//            logOut = log.out();
//        }
//        if (!logOut) {
//            return;
//        }
//
//        String result = ret.toString();
//
//        String methodName = cmethod.getName();
//        if (methodName.startsWith("get") || methodName.startsWith("find") ||
//                methodName.startsWith("search") || methodName.startsWith("select") ||
//                methodName.startsWith("list")) {
//            result = "(hid)";
//        } else {
//            try {
//                result = JSON.toJSONString(ret);
//            } catch (Throwable ignored) {
//            }
//        }
//
//        WebContextUtils.getInstance().getRequest().setAttribute("_resp", result);
//    }

}

